﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace GrayParrot.Core.Filters
{
    /// <summary>
    /// 
    /// </summary>
    /// <seealso cref="GrayParrot.Core.Filters.IFilterBase" />
    [Serializable]
    public class FilterBase : IFilterBase
    {
        /// <summary>
        /// The standard yadcf plugin delimiter...
        /// </summary>
        public const string YADCFDelimiter = "-yadcf_delim-";

        private DateTime? m_periodFrom = null;
        private DateTime? m_periodTo = null;
        private bool m_useDates = false;

        /// <summary>
        /// Gets or sets the delimiter.
        /// </summary>
        /// <value>
        /// The delimiter.
        /// </value>
        /// <remarks>
        /// The delimiter is set by default to the standard yadcf plugin delimiter.
        /// To change the delimiter, set the Delimiter properly...
        /// </remarks>
        public string Delimiter { get; set; }

        public bool UseDates
        {
            get { return m_useDates; }
            set
            {
                m_useDates = value;

                //if ((m_useDates) && (m_periodFrom == null) && (m_periodTo == null))
                //{
                //    m_periodFrom = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 01, 0, 0, 0);
                //    m_periodTo = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 0);
                //}
            }
        }

        public DateTime? PeriodFrom
        {
            get
            {
                if (!m_useDates) return null;

                if (m_periodFrom != null)
                    m_periodFrom = new DateTime(m_periodFrom.Value.Year, m_periodFrom.Value.Month, m_periodFrom.Value.Day, 0, 0, 0);

                return m_periodFrom;

            }
            set { m_periodFrom = value; }
        }

        public DateTime? PeriodTo
        {
            get
            {
                if (!m_useDates) return null;

                if (m_periodTo != null)
                    m_periodTo = new DateTime(m_periodTo.Value.Year, m_periodTo.Value.Month, m_periodTo.Value.Day, 23, 59, 0);

                return m_periodTo;
            }
            set { m_periodTo = value; }
        }

        public FilterBase()
        {

        }

        public virtual string ToTraceString()
        {
            string retValue = string.Empty;

            if (this.UseDates)
            {
                retValue = string.Format("Intervallo date da {0} a {1}; ", this.PeriodFrom, this.PeriodTo);
            }

            return retValue;
        }
    }

    [Serializable]
    public abstract class FilterBase<T> : FilterBase, IFilterBase<T>
    {
        public string SearchPattern { get; set; }

        public FilterBase()
        {
            this.Delimiter = FilterBase.YADCFDelimiter;
        }

        public abstract Expression<Func<T, bool>> SetUpFilter();

        public C GetValueOrDefault<C>(string value)
        {
            if (string.IsNullOrWhiteSpace(value))
                return default(C);
            else
                return (C)Convert.ChangeType(value, typeof(C));
        }

        /// <summary>
        /// Manages the dates.
        /// </summary>
        /// <param name="dateValue">The date value.</param>
        /// <returns>a DateTime if dateValue not contains date range, otherwise return Default(DateTime)</returns>
        public DateTime ManageDates(string dateValue)
        {
            DateTime retValue = default(DateTime);

            // verifico se è presente un filtro range date...
            if (dateValue != null)
            {
                if (dateValue.ToLower().Contains(Delimiter.ToLower()))
                {
                    this.UseDates = true;

                    string[] rangeParts = dateValue.Split(new string[] { Delimiter }, StringSplitOptions.RemoveEmptyEntries);

                    if (rangeParts.Length > 0)
                    {
                        this.PeriodFrom = DateTime.Parse(rangeParts[0]).Date;

                        if (rangeParts.Length == 2)
                        {
                            this.PeriodTo = DateTime.Parse(rangeParts[1]).Date;
                        }
                    }
                }
                else
                {
                    retValue = DateTime.Parse(dateValue).Date;
                }
            }

            return retValue;
        }
    }
}
